package logger

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime"
)

type Logger struct {
	Logger *log.Logger
}

func NewLogger(logFilePath string, prefix string) *Logger {
	var (
		logFile *os.File
		err     error
	)

	_, err = os.Stat(logFilePath)

	if os.IsExist(err) {
		if err := os.Remove(logFilePath); err != nil {
			panic(err)
		}
	}

	_, err = os.Create(logFilePath)
	if err != nil {
		panic(err)
	}

	logFile, err = os.OpenFile(logFilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
	if err != nil {
		panic(err)
	}

	return &Logger{
		Logger: log.New(logFile, prefix, log.LstdFlags|log.LUTC),
	}
}

func (l *Logger) Println(contents ...interface{}) {
	for _, content := range contents {
		fmt.Println(content)
		l.Logger.Println(content)
	}
}

func (l *Logger) Printf(format string, contents ...interface{}) {
	fmt.Printf(format, contents...)
	fmt.Println()
	l.Logger.Printf(format, contents...)
}

func (l *Logger) Debug(format string, contents ...interface{}) {
	_, file, line, _ := runtime.Caller(1)
	l.Logger.SetPrefix("[Debug] " + filepath.Base(file) + ":" + fmt.Sprint(line) + " ")
	if contents == nil {
		l.Println(format)
	} else {
		l.Printf(format, contents...)
	}
}

func (l *Logger) Info(format string, contents ...interface{}) {
	_, file, line, _ := runtime.Caller(1)
	l.Logger.SetPrefix("[Info] " + filepath.Base(file) + ":" + fmt.Sprint(line) + " ")
	if contents == nil {
		l.Println(format)
	} else {
		l.Printf(format, contents...)
	}
}

func (l *Logger) Warn(format string, contents ...interface{}) {
	_, file, line, _ := runtime.Caller(1)
	l.Logger.SetPrefix("[Warn] " + filepath.Base(file) + ":" + fmt.Sprint(line) + " ")
	if contents == nil {
		l.Println(format)
	} else {
		l.Printf(format, contents...)
	}
}

func (l *Logger) Error(format string, contents ...interface{}) {
	_, file, line, _ := runtime.Caller(1)
	l.Logger.SetPrefix("[Error] " + filepath.Base(file) + ":" + fmt.Sprint(line) + " ")
	if contents == nil {
		l.Println(format)
	} else {
		l.Printf(format, contents...)
	}
}

func (l *Logger) Fatal(format string, contents ...interface{}) {
	_, file, line, _ := runtime.Caller(1)
	l.Logger.SetPrefix("[Fatal] " + filepath.Base(file) + ":" + fmt.Sprint(line) + " ")
	if contents == nil {
		l.Println(format)
	} else {
		l.Printf(format, contents...)
	}
}

var almightyLogger *Logger

//var ErrLogger *Logger

func init() {
	file := "pkg/logger/all.log"
	almightyLogger = NewLogger(file, "")
	//ErrLogger = NewLogger(file, "[Error] ")
}

func Debug(format string, contents ...interface{}) {
	_, file, line, _ := runtime.Caller(1)
	almightyLogger.Logger.SetPrefix("[Debug] " + filepath.Base(file) + ":" + fmt.Sprint(line) + " ")
	if contents == nil {
		almightyLogger.Println(format)
	} else {
		almightyLogger.Printf(format, contents...)
	}
}

func Info(format string, contents ...interface{}) {
	_, file, line, _ := runtime.Caller(1)
	almightyLogger.Logger.SetPrefix("[Info] " + filepath.Base(file) + ":" + fmt.Sprint(line) + " ")
	if contents == nil {
		almightyLogger.Println(format)
	} else {
		almightyLogger.Printf(format, contents...)
	}
}

func Warn(format string, contents ...interface{}) {
	_, file, line, _ := runtime.Caller(1)
	almightyLogger.Logger.SetPrefix("[Warn] " + filepath.Base(file) + ":" + fmt.Sprint(line) + " ")
	if contents == nil {
		almightyLogger.Println(format)
	} else {
		almightyLogger.Printf(format, contents...)
	}
}

func Error(format string, contents ...interface{}) {
	_, file, line, _ := runtime.Caller(1)
	almightyLogger.Logger.SetPrefix("[Error] " + filepath.Base(file) + ":" + fmt.Sprint(line) + " ")
	if contents == nil {
		almightyLogger.Println(format)
	} else {
		almightyLogger.Printf(format, contents...)
	}
}

func Fatal(format string, contents ...interface{}) {
	_, file, line, _ := runtime.Caller(1)
	almightyLogger.Logger.SetPrefix("[Fatal] " + filepath.Base(file) + ":" + fmt.Sprint(line) + " ")
	if contents == nil {
		almightyLogger.Println(format)
	} else {
		almightyLogger.Printf(format, contents...)
	}
}
